﻿using System;
using System.Collections.Generic;
using System.Text;

using System.Drawing;
using Microsoft.DirectX;

namespace NGE
{
    public class MenuComponent : Component
    {
        public MenuComponent(string name, Game g)
            : base(name, g)
        {
            focusIndex = -1;
        }

        int getMenuIndex(string name)
        {
            for (int i = 0; i < menus.Count; i++)
            {
                if (menus[i].Name == name)
                {
                    return i;
                }
            }
            return -1;
        }
        int getShowingMenuIndex(string name)
        {
            for (int i = 0; i < showing.Count; i++)
            {
                if (showing[i].Name == name)
                {
                    return i;
                }
            }
            return -1;
        }
        public void LoadMenu(Panelbox panelbox)
        {
            int i = getMenuIndex(panelbox.Name);
            if (i == -1)
            {
                menus.Add(panelbox);
            }
        }

        List<Panelbox> menus = new List<Panelbox>();
        List<Panelbox> showing = new List<Panelbox>();

        int focusIndex;

        bool playerIsInputing;
        public bool PlayerIsInputing
        {
            get
            {
                return playerIsInputing;
            }
            set
            {
                if (value == true)
                {
                    if (IsBusy)
                    {
                        return;
                    }
                }
                playerIsInputing = value;
                if (value == true)
                {
                    game.Inputer.OpenInputLanguage();
                }
                else
                {

                    game.Inputer.CloseInputLanguage();
                }
            }
        }

        int chrCountPerLine = 16;
        int chrLines = 3;
        string playerInputedText = "";
        string PlayerInputedText
        {
            get
            {
                return splite(playerInputedText, 8);
            }
            set
            {
                if (value == "\b")
                {
                    if (playerInputedText == string.Empty)
                    {
                        return;
                    }
                    playerInputedText = playerInputedText.Substring(0, playerInputedText.Length - 1);
                }
                else if (value == "\r")
                {
                    playerInputedText += "\n";
                }
                else
                {
                    if (playerInputedText.Length > chrCountPerLine * chrLines - 1)
                    {
                        return;
                    }
                    string[] lines = (playerInputedText + value).Split(new string[] { "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
                    if (lines.Length == 3)
                    {
                        if (lines[2].Length > chrCountPerLine)
                        {
                            return;
                        }
                    }
                    else if (lines.Length > chrLines)
                    {
                        return;
                    }
                    playerInputedText += value;
                }
            }
        }

        public bool IsBusy
        {
            get
            {
                if (PlayerIsInputing)
                {
                    return true;
                }
                if (showing.Count > 0)
                {
                    return true;
                }
                return false;
            }
        }

        public void FocusOn(int index)
        {
            focusIndex = index;
        }
        public void Close(int index)
        {
            if (showing.Count == 0)
            {
                return;
            }
            showing[index].Close(this, null);
            showing.RemoveAt(index);
            focusIndex = showing.Count - 1;
        }
        public void Close(string name)
        {
            int i = getShowingMenuIndex(name);
            if (i > -1)
            {
                Close(i);
            }
        }
        public void Close()
        {
            if (showing.Count > 0)
            {
                Close(showing.Count - 1);
            }
        }

        public void Refresh(string name, object arg)
        {
            int i = getShowingMenuIndex(name);
            if (i > -1)
            {
                showing[i].Refresh(this, arg);
            }
        }

        public void Open(string name, Vector3 loc, object arg)
        {
            int i = getMenuIndex(name);
            if (i > -1)
            {
                open(menus[i], loc, arg);
            }
        }
        public void Open(string name, object arg)
        {
            int i = getMenuIndex(name);
            if (i > -1)
            {
                open(menus[i], menus[i].Location, arg);
            }
        }
        void open(string file, Vector3 loc, object arg)
        {
            open(loadPanelbox(file),loc, arg);
        }
        void open(Panelbox panelbox, Vector3 loc, object arg)
        {
            for (int i = 0; i < showing.Count; i++)
            {
                if (showing[i].GUID == panelbox.GUID)
                {
                    showing.RemoveAt(i);
                    break;
                }
            }
            //if (arg is string)
            //{
            //    for (int i = 0; i < panelbox.Elements.Count; i++)
            //    {
            //        if (panelbox.Elements[i] is Textbox)
            //        {
            //            ((Textbox)panelbox.Elements[i]).Text = (string)arg;
            //            break;
            //        }
            //    }
            //}
            showing.Add(panelbox);
            focusIndex = showing.Count - 1;
            showing[focusIndex].Open(this, loc, arg);
        }

        Panelbox loadPanelbox(string file)
        {
            FileIndexer fi = new FileIndexer(file);
             Panelbox pb = new  Panelbox(game);
            if (fi.ExtName == ".ngui")
            {
                pb = ( Panelbox)Util.LoadObject(file);
            }
            else if (fi.ExtName == ".ngui.xml")
            {
                pb = ( Panelbox)Util.LoadObjectXML(file, typeof( Panelbox));
            }
            else
            {
                return null;
            }
            return pb;
        }

        void drawPanelbox( Panelbox pb)
        {
            if (pb.IsHide)
            {
                return;
            }
            if (pb.BGImage == null)
            {
                Rectangle zone = new Rectangle(Util.Vector32Point(pb.Location), pb.Size);
                //zone.X /= (int)game.Option.Zoom;
                //zone.Y /= (int)game.Option.Zoom;
                //zone.Width /= (int)game.Option.Zoom;
                //zone.Height /= (int)game.Option.Zoom;
                game.Graph.DrawRectangle( pb.BGColor, zone, true);
            }
            else
            {
                Rectangle zone = new Rectangle(new Point(), pb.Size);
                zone.Width /= (int)game.Option.Zoom;
                zone.Height /= (int)game.Option.Zoom;

                Vector3 v3 = pb.Location;
                //v3.X /= (int)game.Option.Zoom;
                //v3.Y /= (int)game.Option.Zoom;
                game.Graph.DrawImage(pb.BGImage, Color.White, zone, v3, false);
            }
            foreach (MenuElement guie in pb.Elements)
            {
                if (guie is Imagebox)
                {
                    Imagebox ele = (Imagebox)guie;
                    drawImagebox(ele, pb.Location);
                }
                else if (guie is Textbox)
                {
                    drawTextbox((Textbox)guie, pb.Location);
                }
            }
            foreach (Buttonbox bb in pb.Buttonboxes)
            {
                drawButtonbox(bb, pb.Location);
            }
        }

        void drawButtonbox(Buttonbox bb, Vector3 baseloc)
        {
            if (bb.IsHide)
            {
                return;
            }
            Vector3 v3 = Util.Vector3AddVector3(baseloc, bb.Location);
            game.Graph.DrawText(bb.Text, bb.TextColor, bb.TextFont, v3);
        }

        void drawTextbox( Textbox tb, Vector3 baseloc)
        {
            if (tb.IsHide)
            {
                return;
            }
            Vector3 v3 = Util.Vector3AddVector3(baseloc, tb.Location);
            game.Graph.DrawText(tb.Text, tb.TextColor, tb.TextFont, v3);
        }

        void drawImagebox(Imagebox ib, Vector3 baseloc)
        {
            if (ib.IsHide)
            {
                return;
            }

            game.Graph.DrawRectangle(ib.BGColor, ib.Zone, true);
            if (ib.Image == null)
            {
                return;
            } 
            Vector3 v3 = Util.Vector3AddVector3(baseloc, ib.Location);
            game.Graph.DrawImage(ib.Image, v3);
        }

        public override void OnKeyboardEventCode(object sender, int key, KeyboardState ks)
        {
            //foreach (Panelbox pb in showing)
            //{
            //    pb.NotifyKeyboardEvent(key, ks);
            //}

            try
            {
                if (focusIndex > -1)
                {
                    if (showing[focusIndex].IsHide == false)
                    {
                        showing[focusIndex].NotifyKeyboardEvent(key, ks);
                    }
                }
            }
            catch { }
            if (ks == KeyboardState.KeyUp)
            {
                if (key == (int)Microsoft.DirectX.DirectInput.Key.F1)
                {
                    //Open(menuBattleAct, null);
                    //Open("信息", "asdf");
                }
                else if (key == (int)Microsoft.DirectX.DirectInput.Key.F2)
                {
                }
                else if (key == game.Option.KeyY)
                {
                    if (PlayerIsInputing)
                    {
                        if (game.Keyboard[29] == KeyboardState.KeyHold || game.Keyboard[157] == KeyboardState.KeyHold)
                        {
                            //game.PC.Said = PlayerInputedText;
                            //game.PC.SaidStartTime = game.RunningTotalSeconds;
                            //if (game.IsOnline)
                            //{
                            //    game.ClientCOM.UploadPCSayInfo(game.PC.SayInfo);
                            //}

                            PlayerIsInputing = false;
                            playerInputedText = "";
                        }
                    }
                    else
                    {
                        PlayerIsInputing = true;
                    }
                }
                else if (key == game.Option.KeyX)
                {
                    if (PlayerIsInputing)
                    {
                        PlayerIsInputing = false;
                    }
                    else
                    {
                        //Close();
                    }
                }
            }
        }

        public override void OnGamepadEventCode(object sender, int btn, GamepadState gs)
        {
            base.OnGamepadEventCode(sender, btn, gs);
            if (gs == GamepadState.ButtonDown)
            {
                //if (btn == (Xinput.XINPUT_GAMEPAD_LEFT_SHOULDER + Xinput.XINPUT_GAMEPAD_RIGHT_SHOULDER ))
                //{
                //    game.GoFullScreen();
                //}
                //else
                //if (btn == Xinput.XINPUT_GAMEPAD_START)
                //{
                //    game.IsOnline = true;
                //}
                //else if (btn == Xinput.XINPUT_GAMEPAD_A)
                //{
                //    //TalkToNPC();
                //}
                //else if (btn == Xinput.XINPUT_GAMEPAD_B)
                //{
                //    //TalkOver();
                //}
                //else if (btn == Xinput.XINPUT_GAMEPAD_X)
                //{
                //}
                //else if (btn == Xinput.XINPUT_GAMEPAD_Y)
                //{
                //}
                //else if (btn == Xinput.XINPUT_GAMEPAD_LEFT_SHOULDER)
                //{
                //    game.Zoom(0);
                //}
                //else if (btn == Xinput.XINPUT_GAMEPAD_RIGHT_SHOULDER)
                //{
                //    game.Zoom(1);
                //}
            }
        }

        public override void OnInputerEventCode(object sender, object arg)
        {
            if (PlayerIsInputing)
            {
                if (arg is string)
                {
                    string txt = (string)arg;
                    PlayerInputedText = txt;
                }
            }
        }

        string textCursor;

        string splite(string text, int lineCount)
        {
            string txt = "";
            for (int i = 0; i < text.Length; i++)
            {
                if (i > 0)
                {
                    if (i % lineCount == 0)
                    {
                        txt += "\n";
                    }
                }
                txt += text.Substring(i, 1);
            }
            return txt;
        }

        //void drawSpriteSaid(Scene scn, Character chr)
        //{
        //    if (scn == null)
        //    {
        //        return;
        //    }
        //    if (chr == null)
        //    {
        //        return;
        //    }
        //    if (chr.Type != SpriteType.NPC)
        //    {
        //        if (game.RunningTotalSeconds - chr.SaidStartTime > chr.SaidDuration)
        //        {
        //            return;
        //        }
        //    }          
            
        //    string txt = chr.Said;
        //    if (txt == null)
        //    {
        //        return;
        //    }
        //    if (txt == string.Empty)
        //    {
        //        return;
        //    }

        //    Vector3 v3 = Util.Vector3AddVector3(scn.Location, chr.Location);

        //    Size sz = Util.GetTextSize(txt, game.Option.Font.Height);
        //    v3.Y -= sz.Height;
        //    v3.X -= sz.Width / 2;

        //    game.Graph.DrawText(txt, Color.White, game.Option.Font, true, v3);
        //}

        void drawInputedText(string text)
        {
            {
                game.Graph.DrawRectangle(Color.FromArgb(200, Color.Black), new Rectangle(5, 175, 310, 60), true);
                text = splite(text + textCursor, 16);
                //Font font = new Font(game.Option.FontName, game.Option.FontSize, game.Option.FontStyle, GraphicsUnit.Pixel);
                game.Graph.DrawText(text, Color.White, game.Option.Font,  new Vector3(8, 178, 0));
            }
        }

        public override void Heartbeat()
        {
            if ((game.Timer.TotalSeconds - (int)game.Timer.TotalSeconds) > .5)
            {
                textCursor = "_";
            }
            else
            {
                textCursor = "";
            }
            //if (((int)timer.TotalSeconds % 6 == 0))
            {
                delay = game.LoopbackDuration * 1000;
                fps = game.FPS;
            }
        }

        double delay, fps;

        public override void Show()
        {
            foreach (Panelbox pb in showing)
            {
                drawPanelbox(pb);
            }

            if (playerIsInputing)
            {
                drawInputedText(playerInputedText);
            }

            //if (sceneCOM.SCN != null)
            //{
            //    //if (game.PC != null)
            //    //{
            //    //    drawSpriteSaid(game.SCN, game.PC);
            //    //}

            //    {
            //        foreach (Character opc in sceneCOM.CHRs)
            //        {
            //            drawSpriteSaid(sceneCOM.SCN, opc);
            //        }
            //    }
            //}

            //Font font = new Font(game.Option.FontName, game.Option.FontSize, game.Option.FontStyle, GraphicsUnit.Pixel);
            //game.Graph.DrawText("延迟：" + delay.ToString("f1") + " ms\n" + "帧率：" + fps.ToString("f1"), Color.White, game.Option.Font, true, new Vector3(3, 3, 0));
        }
        //SceneComponent sceneCOM
        //{
        //    get
        //    {
        //        return ((SceneComponent)game.GetComponent("SceneCOM"));
        //    }
        //}
    }
}
